package com.zrwl.poscloud.xo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zrwl.poscloud.base.entity.Sequence;
import com.zrwl.poscloud.base.enums.EBusinessType;
import com.zrwl.poscloud.base.enums.EStatus;
import com.zrwl.poscloud.base.superI.SuperServiceImpl;
import com.zrwl.poscloud.commons.holder.RequestHolder;
import com.zrwl.poscloud.commons.utils.ResultUtil;
import com.zrwl.poscloud.commons.utils.StringUtils;
import com.zrwl.poscloud.xo.global.MessageConf;
import com.zrwl.poscloud.xo.global.SQLConf;
import com.zrwl.poscloud.xo.global.SysConf;
import com.zrwl.poscloud.xo.mapper.SequenceMapper;
import com.zrwl.poscloud.xo.service.AdminService;
import com.zrwl.poscloud.xo.service.SequenceService;
import com.zrwl.poscloud.xo.vo.AdminVO;
import com.zrwl.poscloud.xo.vo.SequenceVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * 黑名单序号 服务实现类
 *
 * @author 刘思童 AutoGenerate
 * @date 2021-07-12
 */
@Service
public class SequenceServiceImpl extends SuperServiceImpl<SequenceMapper, Sequence> implements SequenceService {

    @Autowired
    private SequenceService sequenceService;

    @Resource
    private SequenceMapper sequenceMapper;
    @Autowired
    private AdminService adminService;

    @Override
    public IPage<Sequence> getPageList(SequenceVO sequenceVO) {
        QueryWrapper<Sequence> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(sequenceVO.getKeyword()) && !StringUtils.isEmpty(sequenceVO.getKeyword().trim())) {
            queryWrapper.like("name", sequenceVO.getKeyword().trim());
        }
        Page<Sequence> page = new Page<>();
        page.setCurrent(sequenceVO.getCurrentPage());
        page.setSize(sequenceVO.getPageSize());
        queryWrapper.ne(SQLConf.STATUS, EStatus.DISABLED);
        queryWrapper.orderByDesc(SQLConf.CREATE_TIME);
        IPage<Sequence> pageList = sequenceService.page(page, queryWrapper);
        List<Sequence> list = pageList.getRecords();
        pageList.setRecords(list);
        return pageList;
    }

    @Override
    public List<Sequence> getAllList(SequenceVO sequenceVO) {
        QueryWrapper<Sequence> queryWrapper = new QueryWrapper<>();
        queryWrapper.ne(SQLConf.STATUS, EStatus.DISABLED);
        queryWrapper.orderByAsc(SQLConf.CREATE_TIME);
        List<Sequence> list = sequenceService.list(queryWrapper);
        return list;
    }

    @Override
    public String add(SequenceVO sequenceVO) {
        Sequence entity = new Sequence();
        BeanUtils.copyProperties(sequenceVO, entity, SysConf.STATUS);
        entity.insert();
        sequenceVO.setUid(entity.getUid());
        return ResultUtil.successWithMessage(MessageConf.INSERT_SUCCESS);
    }

    @Override
    public String edit(SequenceVO sequenceVO) {
        Sequence entity = sequenceService.getById(sequenceVO.getUid());
        BeanUtils.copyProperties(sequenceVO, entity);
        //entity.setUpdateTime//已通过填充实现，后续可删除(new Date());
        entity.updateById();
        return ResultUtil.successWithMessage(MessageConf.UPDATE_SUCCESS);
    }

    @Override
    public String delete(SequenceVO sequenceVO) {
        Sequence entity = sequenceService.getById(sequenceVO.getUid());
        entity.setStatus(EStatus.DISABLED);
        //entity.setUpdateTime//已通过填充实现，后续可删除(new Date());
        entity.updateById();
        return ResultUtil.successWithMessage(MessageConf.UPDATE_SUCCESS);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public Sequence customizeSelect(SequenceVO sequenceVO) {
        /**
         * 这里采用select for update 语句进入行锁模式(已经添加需要测试)
         * 对应表已添加ownerType,ownerUid,codeType联合索引
         */
        Sequence entity = sequenceMapper.getAssignSequence(sequenceVO);
        if (entity != null) {
            if (String.valueOf(entity.getNextCode()).length() > entity.getMaxLength()) {
                throw new RuntimeException("序列号突破最大值无法添加");
            }
        }
        if (entity == null) {
            Sequence sequence = new Sequence();
            EBusinessType eBusinessType = new EBusinessType();
            int nextCode = 0, maxLength = 0;
            if (sequenceVO.getBusiType() == null) {//所有代码都迭代为新的枚举类后此方案启用
                String[] CON = eBusinessType.getConfigure(sequenceVO.getCodeType()).split(",");
                nextCode = Integer.valueOf(CON[0]);
                maxLength = Integer.valueOf(CON[1]);
            } else {
                nextCode = sequenceVO.getBusiType().getStart();
                maxLength = sequenceVO.getBusiType().getLength();
            }
            sequence.setCodeType(sequenceVO.getCodeType());
            sequence.setOwnerUid(sequenceVO.getOwnerUid());
            sequence.setOwnerType(sequenceVO.getOwnerType());
            sequence.setOwnerCode("0000");
            sequence.setNextCode(nextCode);
            sequence.setMaxLength(maxLength);
            sequence.insert();
            entity = sequence;
        }
        entity.setNextCode(entity.getNextCode() + 1);
        //entity.setUpdateTime//已通过填充实现，后续可删除(new Date());
        entity.updateById();
        entity.setNextCode(entity.getNextCode() - 1);
        return entity;
    }

    @Override
    public Sequence customizeSelect(int ownerType, String ownerUid, int codeType) {
        SequenceVO sequenceVO = new SequenceVO();
        sequenceVO.setOwnerType(ownerType);
        sequenceVO.setOwnerUid(ownerUid);
        sequenceVO.setCodeType(codeType);
        return sequenceService.customizeSelect(sequenceVO);
    }

    @Override
    public Sequence customizeSelect(SequenceVO sequenceVO, String purpose) {
        QueryWrapper<Sequence> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("code_type", sequenceVO.getCodeType());
        queryWrapper.eq("owner_type", sequenceVO.getOwnerType());
        queryWrapper.eq("owner_uid", sequenceVO.getOwnerUid());
        Sequence entity = sequenceService.getOne(queryWrapper);

        if (entity == null) {
            Sequence sequence = new Sequence();
            EBusinessType eBusinessType = new EBusinessType();
            String[] CON = eBusinessType.getConfigure(sequenceVO.getCodeType()).split(",");
            sequence.setCodeType(sequenceVO.getCodeType());
            sequence.setOwnerUid(sequenceVO.getOwnerUid());
            sequence.setOwnerType(sequenceVO.getOwnerType());
            sequence.setOwnerCode("0000");
            sequence.setNextCode(Integer.valueOf(CON[0]));
            sequence.setMaxLength(Integer.valueOf(CON[1]));
            sequence.insert();
            entity = sequence;
        }
        return entity;
    }

    @Override
    //生成流水号
    public String generateSerialCode(Sequence sequence) {
        String ownerType = "";
        String ownerCode = sequence.getOwnerCode();
        String codeType = "";
        String nextCode = "";
        String str = "";
        ownerType = sequence.getOwnerType() + "";
        codeType = sequence.getCodeType() + "";
        for (int i = 0; i < (sequence.getMaxLength() - String.valueOf(sequence.getNextCode()).length() - 3); i++) {
            str += "0";
        }
        String randStr = "";//加入随机3位数
        for (int i = 0; i < 3; i++) {
            randStr = randStr + ((int) (Math.random() * 10));
        }
        nextCode = str + sequence.getNextCode();
        str = ownerType + ownerCode + codeType + nextCode + randStr;
        return str;
    }

    @Override
    public String generateNumber(Sequence sequence) {
        String str = "";
        String ownerCode = sequence.getOwnerCode();
        String nextCode = "";
        for (int i = 1; i < sequence.getMaxLength() - String.valueOf(sequence.getNextCode()).length(); i++) {
            str += "0";
        }
        nextCode = ownerCode.substring(ownerCode.length() - 1) + str + sequence.getNextCode();
        return nextCode;
    }

    @Override
    //包装的生成各种流水号方法（调用更加方便）调取传递参数需加入到枚举变量中
    public String createVariousCode(Integer type) throws Exception {
        HttpServletRequest request = RequestHolder.getRequest();
        String ownerUid = null;
        Integer ownerType = null;
        AdminVO adminVO = adminService.getMe();
        ownerUid = adminVO.getUid();
        ownerType = 0;
        if (ownerType != null && ownerUid != null && type != null) {
            SequenceVO sequenceVO = new SequenceVO();
            sequenceVO.setOwnerType(ownerType);
            sequenceVO.setOwnerUid(ownerUid);
            sequenceVO.setCodeType(type);
            Sequence sequence = customizeSelect(sequenceVO);
            String code = generateSerialCode(sequence);
            return code;
        } else {
            throw new RuntimeException("系统错误!非法请求");
        }
    }

    @Override
    //包装的生成各种流水号方法（调用更加方便）调取传递参数需加入到枚举变量中(提供给不从session中获取信息时拿编号)
    public String createVariousCode(String ownerUid, Integer ownerType, Integer type) throws Exception {
        if (ownerType != null && ownerUid != null && type != null) {
            SequenceVO sequenceVO = new SequenceVO();
            sequenceVO.setOwnerType(ownerType);
            sequenceVO.setOwnerUid(ownerUid);
            sequenceVO.setCodeType(type);
            Sequence sequence = customizeSelect(sequenceVO);
            String code = generateSerialCode(sequence);
            return code;
        } else {
            throw new RuntimeException("系统错误!非法请求");
        }
    }

    @Override
    //只获取整型号码不拼接单号 调取传递参数需加入到枚举变量中(提供给不从session中获取信息时拿编号)
    public Integer getVariousCode(String ownerUid, Integer ownerType, Integer type) throws Exception {
        if (ownerType != null && ownerUid != null && type != null) {
            SequenceVO sequenceVO = new SequenceVO();
            sequenceVO.setOwnerType(ownerType);
            sequenceVO.setOwnerUid(ownerUid);
            sequenceVO.setCodeType(type);
            Sequence sequence = customizeSelect(sequenceVO);
            Integer code = sequence.getNextCode();
            return code;
        } else {
            throw new RuntimeException("系统错误!非法请求");
        }
    }

}
